using Roots.UI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Roots
{
    public class InputHandler : MonoBehaviour
    {
        [SerializeField] Game game;

        [SerializeField] Grid grid;
        [SerializeField] CameraFollow cameraFollow;
        [SerializeField] UiHandler uiHandler;
        [SerializeField] RootsHandler rootsHandler;
        [SerializeField] ScoreManager scoreManager;

        [SerializeField] ParticleSystem dirtEffect;

        [SerializeField] LayerMask objectLayer;

        [Header("Help")]
        [SerializeField] float maxErrorCount = 5;
        [SerializeField] float errorClearTime = 15f;

        [Header("Cursor")]
        [SerializeField] GridCursor cursor;
        [SerializeField] CursorData[] cursorDatas;

        private Vector3 mouseWorldPos = Vector3.zero;
        private Vector3Int mouseGridPos = Vector3Int.zero;
        private Vector3Int previousMouseGridPos = new(0, 100);

        //���������ʱ��ʾ����
        private int errorCount = 0;
        private float errorTimer = 0f;

        private void Start()
        {
            cursor.InitAtRoot(rootsHandler.Root);
            cursorDatas[0].Apply();
        }

        // Update is called once per frame
        void Update()
        {
            HandleUiInput();
            if (uiHandler.IsUiOpen) return;

            if (errorTimer > 0f)
            {
                errorTimer -= Time.deltaTime;
                //�Զ�����������
                if (errorTimer <= 0f)
                    errorCount = 0;
            }

            //���λ��
            mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            mouseGridPos = grid.WorldToCell(mouseWorldPos);

            HandleUpdateCursor();

            //���ó�ʼ����
            if (!game.Started)
            {
                PlacingFirstRoot();
                return;
            }

            //�������ê��
            cameraFollow.SetPosition(mouseWorldPos);

            HandlePlacingRoot();
        }

        private void AddErrorCount()
        {
            errorCount++;
            errorTimer = errorClearTime;

            if (errorCount >= maxErrorCount)
            {
                uiHandler.ShowHelpBubble();
                errorCount = 0;
                errorTimer = 0f;
            }
        }

        private void PlacingFirstRoot()
        {
            if (Input.GetMouseButtonDown(0))
            {
                if (rootsHandler.PlaceFirstRoot(mouseGridPos))
                {
                    cursor.gameObject.SetActive(false);

                    dirtEffect.transform.position = mouseWorldPos;
                    dirtEffect.Play();
                }
            }
        }

        private void HandleUpdateCursor()
        {
            if (!mouseGridPos.Equals(previousMouseGridPos))
            {
                UpdateCursor();
                previousMouseGridPos = mouseGridPos;
            }
        }

        private void UpdateCursor()
        {
            var cellPos = grid.GetCellCenterWorld(mouseGridPos);
            //��ȡ��Դ
            var collider = Physics2D.OverlapPoint(cellPos, layerMask: objectLayer);
            if (collider != null && collider.TryGetComponent(out Resource resource))
            {
                cursorDatas[resource.type + 1].Apply();
            }
            else if (rootsHandler.HasObstacle(mouseGridPos))
                cursorDatas[4].Apply();
            else cursorDatas[0].Apply();

            if (game.Started)
            {
                cursor.transform.position = cellPos;

                if (rootsHandler.CanPlaceRoot(mouseGridPos, out int neighborsCount))
                {
                    cursor.SetLosing(scoreManager.Losing);
                    cursor.gameObject.SetActive(true);
                    cursor.SetAllowed(true);
                }
                else if (neighborsCount > 1)
                {
                    cursor.gameObject.SetActive(true);
                    cursor.SetAllowed(false);
                }
                else
                {
                    cursor.gameObject.SetActive(false);
                }
            }
        }

        private void HandlePlacingRoot()
        {
            if (Input.GetMouseButtonDown(0))
            {
                if (rootsHandler.CanPlaceRoot(mouseGridPos, out int _))
                {
                    if (rootsHandler.PlaceRoot(mouseGridPos, objectLayer))
                    {
                        UpdateCursor();

                        //������Ч
                        if (!dirtEffect.isPlaying)
                        {
                            dirtEffect.transform.position = mouseWorldPos;
                            dirtEffect.Play();
                        }
                    }
                }
                else
                {
                    AddErrorCount();
                }
            }
        }

        private void HandleUiInput()
        {
            if (!game.Started) return;
            if (Input.GetKeyDown(KeyCode.Escape))
                uiHandler.ToggleMenu();
        }
    }
}